use clipboard::ClipboardContext;
use clipboard::ClipboardProvider;
use iced::widget::{column, container, text};
use iced::window;
use iced::{Application, Command, Element, Settings, Subscription, Theme};
use std::path::PathBuf;

#[derive(Debug, Clone)]
enum Message {
    FileDropped(Option<PathBuf>),
    OpenFile,
}

struct MyApp {
    file_path: Option<PathBuf>,
    md5_hash: Option<String>,
}

impl Application for MyApp {
    type Executor = iced::executor::Default;
    type Message = Message;
    type Theme = Theme;
    type Flags = ();
    fn new(_flags: ()) -> (MyApp, Command<Message>) {
        (
            MyApp {
                file_path: None,
                md5_hash: None,
            },
            Command::none(),
        )
    }

    fn title(&self) -> String {
        String::from("MD5 Calculator")
    }

    fn update(&mut self, message: Message) -> Command<Message> {
        match message {
            Message::FileDropped(path) => {
                if let Some(path_buf) = &path {
                    self.file_path = Some(PathBuf::from(path_buf));
                    self.md5_hash = calculate_md5(&path_buf);
                }
            }
            Message::OpenFile => {
                // let file_dialog = iced::futures::FileDialog::new();
                // return Command::perform(file_dialog.pick_file(), Message::FileDropped);
            }
        }
        Command::none()
    }

    fn subscription(&self) -> Subscription<Message> {
        iced::event::listen().map(|event| match event {
            iced::Event::Window(window::Id::MAIN, iced::window::Event::FileDropped(stream)) => {
                Message::FileDropped(Some(stream))
            }
            // _ => Message::FileDropped(iced::futures::stream::Stream::empty()),
            _ => Message::OpenFile,
        })
    }

    fn view(&self) -> Element<Message> {
        let file_label = text(
            self.file_path
                .as_ref()
                .map(|path| format!("File: {}", path.display()))
                .unwrap_or_else(|| {
                    "Drag and drop a file here. MD5 will be written to the clipboard by default"
                        .to_string()
                }),
        );

        let md5_label = text(
            self.md5_hash
                .as_ref()
                .map(|hash| format!("MD5: {}", hash))
                .unwrap_or_else(|| "".to_string()),
        );

        let open_button = iced::widget::button::Button::new(text("Open File"))
            .on_press(Message::OpenFile)
            .padding(10)
            .width(100);

        let content = column![file_label, open_button, md5_label,]
            .spacing(10)
            .padding(10);

        container::Container::new(content)
            .width(iced::Length::Fill)
            .height(iced::Length::Fill)
            .center_x()
            .center_y()
            .into()
    }
}

fn calculate_md5(file_path: &PathBuf) -> Option<String> {
    use std::fs::File;
    use std::io::Read;

    let mut file = File::open(file_path).ok()?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer).ok()?;

    let digest = md5::compute(&buffer);
    let str = format!("{:x}", digest);
    // 获取原始文件名并添加_md5.txt后缀
    let file_name = file_path.file_name().unwrap().to_str().unwrap();
    let new_file_name = format!("{}_md5.txt", file_name);

    // 生成新文件路径，直接添加新后缀
    let new_file_path = file_path.with_file_name(new_file_name);

    // 将MD5写入剪贴板

    let mut ctx: ClipboardContext = ClipboardContext::new().unwrap();
    ctx.set_contents(str.clone()).unwrap();

    // 保存MD5摘要到新文件
    std::fs::write(&new_file_path, &str).unwrap();
    Some(str)
}

fn main() -> iced::Result {
    MyApp::run(Settings::default())
}
